﻿/**	@file		std_iterator.hpp
 *	@date		(2007-05-05 00:36:31)/(2011-09-11 23:12:43)
 *-----------------------------------------------------------------------------
 *	@version	1.0.5.7
 *	@author		Nick Shallery	(nicknide@gmail.com)
 *	@copyright	YOU HAVE ALL LEFT WITH THIS CODE WHILE YOU KEEP COMMENT IN EVERY COPY.
 *-----------------------------------------------------------------------------
**/

#if			!defined(__LOLIX__TOY__STD_ITERATOR__NICK__K_IN_G__)
#define		__LOLIX__TOY__STD_ITERATOR__NICK__K_IN_G__
//==============================================================================
//--------------------------------------------------------------------------


#if			!defined(__LOLIX__LOLI_X_CFG__K_IN_G__)
	#include	"../lolix_cfg.h"
#endif	//	!defined(__LOLIX__LOLI_X_CFG__K_IN_G__)

#if				!defined(__LOLIX__LOLI_X_MACRO__K_IN_G__)
	#include	"../lolix_macro.h"
#endif	//	!defined(__LOLIX__LOLI_X_MACRO__K_IN_G__)

#if			LOLIX_CFG__IS_DEBUG
	#if			!defined(__LOLIX__TOY__L_X_ASSERT_NICK__K_IN_G__)
		#include	"./lx_assert.h"
	#endif	//	defined(__LOLIX__TOY__L_X_ASSERT_NICK__K_IN_G__)
#endif	//	LOLIX_CFG__IS_DEBUG


namespace lolix{namespace toy{
	namespace _help{
		namespace _help_for_iter_add{
			template<typename _Itr, typename _TDif>
			LOLIX_INLINE_CALL _Itr operator + (_Itr itr, _TDif dif)
				{
				if ( dif > 0 )
					{
					for ( ; dif; --dif )
						++itr;
					}
				else if ( dif < 0 )
					{
					for ( ; dif; ++dif )
						--itr;
					}
				return itr;
				}

			template<typename _Itr, typename _TDif>
			LOLIX_INLINE_CALL	const _Itr _move_iterator(_Itr itr, _TDif dif)
				{
				return itr + dif;
				}
			}
		template<typename _Itr>
		LOLIX_INLINE_CALL difference_type calc_distance(_Itr l, _Itr r, ...)
			{
			difference_type v = 0;
			while (l != r)
				++v, ++l;
			return v;
			}
		template<typename _Itr>
		LOLIX_INLINE_CALL difference_type calc_distance(_Itr l, _Itr r, decltype(r-l))
			{
			return r - l;
			}

		/**
		* \brief	尝试返回右值引用的一个辅助对象
		* \tparam	_TyRef	引用的类型
		* \remark	此一般化模板返回普通的引用
		**/
		template<typename _TyRef>struct ret_rref{template<typename _Ty>static LOLIX_INLINE_CALL _TyRef get_ref(_Ty* pval){return *pval;}};
		/**
		* \brief	尝试返回右值引用的一个辅助对象
		* \tparam	_Ty	对象的类型
		* \remark	此特化模板返回右值引用
		**/
		template<typename _Ty>struct ret_rref<_Ty&&>{static LOLIX_INLINE_CALL _Ty&& get_ref(_Ty* pval){return lolix::forward<_Ty>(*pval);}};
	}

	template<typename _Ty, typename _Ref, typename _CRef>
	class	value_iterator
		{
			typedef	value_iterator	this_type;
			typename remove_reference<_Ty>::type*	_v;
			difference_type	_pos;
		public:
			typedef typename remove_reference<_Ty>::type value_type;
			typedef difference_type					difference_type;
			typedef this_type						pointer;
			typedef _Ref							reference;
			typedef const this_type					const_pointer;
			typedef _CRef							const_reference;

			LOLIX_INLINE_CALL	value_iterator(reference o, difference_type pos): _v(address_of(o)), _pos(pos){}
			LOLIX_INLINE_CALL	value_iterator(reference o): _v(address_of(o)), _pos(0){}

			LOLIX_INLINE_CALL	const value_type* operator->(void)const
				{
				return _v;
				}
			LOLIX_INLINE_CALL	value_type* operator->(void)
				{
				return _v;
				}
			LOLIX_INLINE_CALL	const_reference operator*(void)const
				{
				return *_v;
				}
			LOLIX_INLINE_CALL	reference operator*(void)
				{
				return lolix::toy::_help::ret_rref<reference>::get_ref(_v);
				}
			LOLIX_INLINE_CALL	this_type& operator ++(void)
				{
				++_pos;
				return *this;
				}
			LOLIX_WARNING_FOR_PERFORMANCE("use prefix increment operator instead")
			LOLIX_INLINE_CALL	this_type& operator ++(int)
				{
				this_type tmp(*this);
				++*this;
				return tmp;
				}
			LOLIX_INLINE_CALL	this_type& operator --(void)
				{
				--_pos;
				return *this;
				}

			LOLIX_WARNING_FOR_PERFORMANCE("use prefix decrement operator instead")
			LOLIX_INLINE_CALL	this_type& operator --(int)
				{
				this_type tmp(*this);
				--*this;
				return tmp;
				}
			LOLIX_INLINE_CALL	this_type& operator +=(difference_type pos)
				{
				_pos += pos;
				return *this;
				}
			LOLIX_INLINE_CALL	this_type& operator -=(difference_type pos)
				{
				_pos -= pos;
				return *this;
				}
			LOLIX_INLINE_CALL	this_type operator +(difference_type pos)const
				{
				this_type tmp(*this);
				tmp += pos;
				return tmp;
				}
			LOLIX_INLINE_CALL	this_type operator -(difference_type pos)const
				{
				this_type tmp(*this);
				tmp -= pos;
				return tmp;
				}
			LOLIX_INLINE_CALL	const_reference operator[](difference_type)const
				{
				return (const_reference)(*_v);
				}

			LOLIX_INLINE_CALL	difference_type operator - (const this_type& o)const
				{
				LOLIX_ASSERT(_v == o._v, "lolix::toy::value_iterator::operator - (const this_type&o).");
				return _pos - o._pos;
				}

#undef		__LOLIX__TMP__DEFINE__LOGIC_CMP_FUNC
#define		__LOLIX__TMP__DEFINE__LOGIC_CMP_FUNC(__lx_v__)		\
			LOLIX_INLINE_CALL	bool operator __lx_v__ (const this_type& o)const{ LOLIX_ASSERT(_v == o._v, "wrong compera."); return _pos __lx_v__ o._pos;}
			__LOLIX__TMP__DEFINE__LOGIC_CMP_FUNC(<);
			__LOLIX__TMP__DEFINE__LOGIC_CMP_FUNC(<=);
			__LOLIX__TMP__DEFINE__LOGIC_CMP_FUNC(>);
			__LOLIX__TMP__DEFINE__LOGIC_CMP_FUNC(>=);
#undef		__LOLIX__TMP__DEFINE__LOGIC_CMP_FUNC
			LOLIX_INLINE_CALL	bool operator == (const this_type& o)const
				{
				return _v == o._v && _pos == o._pos;
				}
			LOLIX_INLINE_CALL	bool operator != (const this_type& o)const
				{
				return !((*this) == o);
				}

		};

	template<typename _Ty, typename _Ref, typename _CRef>
	LOLIX_INLINE_CALL	value_iterator<_Ty, _Ref, _CRef> operator + ( typename value_iterator<_Ty, _Ref, _CRef>::difference_type pos, const value_iterator<_Ty, _Ref, _CRef> iter )
		{
		return iter + pos;
		}

	template<typename _Ty>
	LOLIX_INLINE_CALL	value_iterator<_Ty, _Ty&, const _Ty&> make_value_iterator(_Ty& r)
		{
		return value_iterator<_Ty, _Ty&, const _Ty&>(r);
		}

	template<typename _Ty, typename _TDiff>
	LOLIX_INLINE_CALL	value_iterator<_Ty, _Ty&, const _Ty&> make_value_iterator(_Ty& r, _TDiff pos)
		{
		return value_iterator<_Ty, _Ty&, const _Ty&>(r, pos);
		}

#if			LOLIX_CFG__SUPPORT_CPP_11
	template<typename _Ty>
	LOLIX_INLINE_CALL	value_iterator<_Ty, _Ty&&, _Ty&&> make_value_iterator(_Ty&& r)
		{
		return value_iterator<_Ty, _Ty&&, _Ty&&>(lolix::forward<_Ty>(r));
		}
	template<typename _Ty, typename _TDiff>
	LOLIX_INLINE_CALL	value_iterator<_Ty, _Ty&&, const _Ty&> make_value_iterator(_Ty&& r, _TDiff pos)
		{
		return value_iterator<_Ty, _Ty&&, const _Ty&>(lolix::forward<_Ty>(r), pos);
		}
#endif	//	LOLIX_CFG__SUPPORT_CPP_11
	template<typename _Itr, typename _TDif>
	LOLIX_INLINE_CALL	const _Itr	move_iterator(_Itr itr, _TDif dif)
		{
		return _help::_help_for_iter_add::_move_iterator<_Itr, _TDif>(itr, dif);
		}

	template<class _RanIt>
	class reverse_iterator
		: public _RanIt
	{	// wrap iterator to run it backwards
		typedef reverse_iterator<_RanIt> _Myt;
		typedef _RanIt base_type;
	public:
		typedef typename _RanIt::difference_type difference_type;
		typedef typename _RanIt::pointer pointer;
		typedef typename _RanIt::reference reference;
		typedef _RanIt iterator_type;

		LOLIX_INLINE_CALL reverse_iterator()
			{	// construct with default wrapped iterator
			}

		LOLIX_INLINE_CALL explicit reverse_iterator(_RanIt _Right)
			: base_type(_Right)
			{	// construct wrapped iterator from _Right
			}

		template<class _Other>
		LOLIX_INLINE_CALL reverse_iterator(const reverse_iterator<_Other>& _Right)
			: base_type(_Right)
			{	// initialize with compatible base
			}

		template<class _Other>
		LOLIX_INLINE_CALL _Myt& operator=(const reverse_iterator<_Other>& _Right)
			{	// assign from compatible base
			base_type.operator=(_Right);
			return (*this);
			}

		template<typename _Other>
		LOLIX_INLINE_CALL bool operator == (const _Other& o)const
			{
			return _RanIt::operator==(o);
			}

		template<typename _Other>
		LOLIX_INLINE_CALL bool operator != (const _Other& o)const
			{
			return _RanIt::operator!=(o);
			}

		LOLIX_INLINE_CALL _Myt& operator++()
			{	// preincrement
			base_type::operator --();
			return (*this);
			}

		LOLIX_INLINE_CALL _Myt operator++(int)
			{	// postincrement
			auto _Tmp = *this;
			++*this;
			return (_Tmp);
			}

		LOLIX_INLINE_CALL _Myt& operator--()
			{	// predecrement
			base_type::operator ++();
			return (*this);
			}

		LOLIX_INLINE_CALL _Myt operator--(int)
			{	// postdecrement
			auto _Tmp = *this;
			--*this;
			return (_Tmp);
			}

		LOLIX_INLINE_CALL _Myt& operator+=(difference_type _Off)
			{	// increment by integer
			base_type::operator-=(_Off);
			return (*this);
			}

		LOLIX_INLINE_CALL _Myt operator+(difference_type _Off) const
			{	// return this + integer
			_Myt _Tmp = *this;
			return (_Tmp += _Off);
			}

		LOLIX_INLINE_CALL _Myt& operator-=(difference_type _Off)
			{	// decrement by integer
			base_type::operator += (_Off);
			return (*this);
			}

		LOLIX_INLINE_CALL _Myt operator-(difference_type _Off) const
			{	// return this - integer
			_Myt _Tmp(*this);
			return (_Tmp -= _Off);
			}

		LOLIX_INLINE_CALL reference operator*() const
			{	// return designated value
			_RanIt _Tmp = *this;
			return (*--_Tmp);
			}

		LOLIX_INLINE_CALL pointer operator->() const
			{	// return pointer to class object
			return (&**this);
			}
	};


	template<typename Ipt>
	LOLIX_INLINE_CALL lolix::size_type distance(Ipt l, Ipt r)
		{
		return _help::calc_distance(l, r, 0);
		}
}}

//--------------------------------------------------------------------------
//==============================================================================
#endif	//	!defined(__LOLIX__TOY__STD_ITERATOR__NICK__K_IN_G__)
